package pf

import (
	. "chess_platform/internal/common"
	"chess_platform/models/client"
	"chess_platform/models/partner"
	"fmt"
	"github.com/astaxie/beego/orm"
	"time"
)

//[h5]钻石
type CardController struct {
	GrantController
}

func (b *CardController) URLMapping() {
	b.Mapping("StatCard", b.StatCard)
	b.Mapping("List", b.List) //代理的钻石买卖流水
	b.Mapping("GiveCard", b.GiveCard)
	b.Mapping("ListAgentPlayer", b.ListAgentPlayer)
	b.Mapping("HandleTopUp", b.HandleTopUp)
	b.Mapping("ListCard", b.ListCard)
	b.Mapping("ListGiveCard", b.ListGiveCard)

}

// @Title 统计当前代理累计买，累计卖了多少张钻石,剩余钻石数
// @Description 统计当前代理累计买，累计卖了多少张钻石,剩余钻石数
// @Success 0 {object} common.StatCard
// @router /stat-card [post]
func (b *CardController) StatCard() {
	stat, err := partner.StatCardInfo(b.Uid)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	stat.ConsumeCard = partner.PlayerConsumeCard(b.Uid)
	b.Res.Data = stat
	b.ResponseSuccess()
}

// @Title 钻石买卖流水
// @Description 钻石买卖流水
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Param   type         body   int     false      "1-买房卡,2-卖房卡(代充),4-送房卡,5-获赠房卡,6-系统赠送"
// @Param   player_id    body   int     false      "搜索玩家id"
// @Success 0 {object} []common.CardRecord 钻石流水列表
// @router /list [post]
func (b *CardController) List() {
	var p ListCardParams
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}

	cr, count, err := partner.ListCardRecord(p, b.Uid)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = cr
	b.Res.Count = count
	b.ResponseSuccess()
}

// @Title 赠送钻石
// @Description 赠送钻石
// @Param   id    body    int true      "赠送钻石数量对应列表的id"
// @Param   uid   body    int true      "被赠送人的id"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /give-card [post]
func (b *CardController) GiveCard() {
	type Params struct {
		Uid int64 `json:"uid" valid:"Required"`
		Id  int64 `json:"id" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	card, err := partner.CardById(p.Id, AgentGiveCard)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if card == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		b.Response()
		return
	}

	//先判断下获赠人是否已经激活了成为正式代理了，如果不是不能获赠
	field := []string{"status"}
	ru, err := partner.SpecifyUserInfoById(p.Uid, field)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if ru == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		b.Response()
		return
	}
	if ru.Status != FirstTopUpSuccess {
		b.Res.Code = ErrAgentInactive
		b.Res.Msg = MsgErrAgentInactive
		b.Response()
		return
	}

	//首先判断下赠送者的钻石数量够不够赠送
	cc, err := partner.CardCashById(b.Uid)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if cc.Uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		LogPF.Error(fmt.Sprintf("代理:%d在表%v没有记录", b.Uid, TablePfCardCash))
		b.Response()
		return
	}

	//现在代理一充值就直接代充到代理的游戏账号里了，所以这里赠送是没有钻石可以赠送的
	if cc.CardNum < card.Num {
		b.Res.Code = ErrCardNotEnough
		b.Res.Msg = MsgErrCardNotEnough
		b.Response()
		return
	}

	o := orm.NewOrm()
	o.Using(DBChessCenter)
	o.Begin()
	defer o.Rollback()
	//减去赠送人的钻石数量
	gn, err := partner.UpdateCard(-card.Num, b.Uid, false, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if gn == 0 {
		o.Rollback()
		msg := fmt.Sprintf("代理:%d赠送钻石在减少钻石数:%d时失败", b.Uid, card.Num)
		LogPF.Notice(msg)
		b.ResponseFail("赠送钻石失败")
		return
	}

	//加上获赠送人的钻石数量
	rn, err := partner.UpdateCard(card.Num, p.Uid, false, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if rn == 0 {
		o.Rollback()
		msg := fmt.Sprintf("代理:%d赠送给代理:%d钻石在加上钻石数:%d时失败", b.Uid, p.Uid, card.Num)
		LogPF.Notice(msg)
		b.ResponseFail("赠送钻石失败")
		return
	}
	//赠送人的角度
	giveCR := map[string]interface{}{
		"agent_id":    b.Uid,
		"player_id":   p.Uid,
		"card_num":    -card.Num,
		"type":        GiveRoomCard,
		"create_time": time.Now().Unix(),
	}
	//获赠人的角度
	receiveCR := map[string]interface{}{
		"agent_id":    p.Uid,
		"player_id":   b.Uid,
		"card_num":    card.Num,
		"type":        ReceiveRoomCard,
		"create_time": time.Now().Unix(),
	}
	_, err = partner.NewCardRecord(giveCR, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	_, err = partner.NewCardRecord(receiveCR, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	o.Commit()
	b.ResponseSuccess()
}

// @Title 在一段时间内在此代理充值过的玩家列表
// @Description 在一段时间内在此代理充值过的玩家列表
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Success 0 {object} []common.AgentPlayer 玩家列表
// @router /list-agent-player [post]
func (b *CardController) ListAgentPlayer() {
	var p ListParams
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	play, count, err := partner.ListAgentPlayer(p, b.Uid)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if count == 0 {
		b.Res.Code = ErrNoData
		b.Res.Msg = MsgErrNoData
		b.Response()
		return
	}
	o := orm.NewOrm()
	o.Using(DBChess)
	for _, v := range play {
		u, err := client.QueryUserInfoById(v.PlayerId, o)
		if err != nil {
			LogPF.Error(b.DatabaseError(err.Error()))
			return
		}
		v.Nickname = u.Nickname
		v.HeadImgUrl = u.ImageUrl
	}
	b.Res.Data = play
	b.Res.Count = count
	b.ResponseSuccess()
}

// @Title 代充钻石
// @Description 代充钻石
// @Param   num         body    int true      "钻石数量"
// @Param   player_id   body    int true      "玩家id"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /handle-top-up [post]
func (b *CardController) HandleTopUp() {
	type Params struct {
		Num      int64 `json:"num"`
		PlayerId int64 `json:"player_id"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	//最小充值数量为1
	b.Valid.Min(p.Num, 1, "num").Message("请输入有效的充值数量")
	b.Valid.Required(p.PlayerId, "player_id").Message("请输入充值玩家ID")
	if !b.VerifyParamsError() {
		return
	}
	dbUser, err := client.QueryUserInfoById(p.PlayerId)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if dbUser.Uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = fmt.Sprintf("玩家ID:%v不存在,请检查", p.PlayerId)
		b.Response()
		return
	}

	//首先判断下代理的钻石数量够不够充值
	cc, err := partner.CardCashById(b.Uid)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if cc.Uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		LogPF.Error(fmt.Sprintf("代理:%d在表%v没有记录", b.Uid, TableH5CardCash))
		b.Response()
		return
	}
	/*
		1. 首先判断代理的代理账号里的钻石够不够,如果够，直接使用代理帐号把钻石充值到其他玩家游戏帐号
		2. 代理帐号钻石如果不够,则判断代理的游戏帐号里是否够,如果够，把帐号从游戏帐号回充到代理帐号，
			然后再充值到其他玩家游戏帐号，如果不够，则提示钻石不足
	*/
	//代理帐号钻石不足
	if cc.CardNum < p.Num {
		//判断代理游戏帐号钻石够不够
		ok := client.ChangeAccountValueFromLobby(b.Uid, -p.Num,
			0, 0, ACCTRAN_OPER_TYPE_TransferCard, 0)
		if !ok { //不够
			b.ResponseFail("钻石不足,代充失败")
			return
		}
		//游戏帐号里钻石足够,回充到代理的代理帐号
		o := NewDBOrm(DBChessPartner)
		o.Begin()
		defer o.Rollback()
		//回充记录
		transferCR := map[string]interface{}{
			"agent_id":    b.Uid,
			"player_id":   b.Uid,
			"card_num":    p.Num,
			"type":        TransferCard,
			"create_time": time.Now().Unix(),
		}
		_, err = partner.NewCardRecord(transferCR, o)
		if err != nil {
			o.Rollback()
			//把钻石还回去
			ok := client.ChangeAccountValueFromLobby(b.Uid, p.Num,
				0, 0, ACCTRAN_OPER_TYPE_TransferCard, 0)
			if !ok {
				eventLog := map[string]interface{}{
					"module":     ModuleSystem,
					"event_type": EventPlay,
					"user_type":  Agent,
					"uid":        b.Uid,
					"msg":        fmt.Sprintf("游戏服返回失败,把钻石还回去失败,请联系开发人员"),
				}
				go NewEventLog(eventLog)
				LogPF.Error(fmt.Sprintf("游戏服返回失败,合伙人代理(ID:%v)把钻石(%v)回充到游戏帐号失败", b.Uid, p.Num))
				LogPF.Error(b.DatabaseError(err.Error()))
				return
			}
		}
		//钻石数量加到代理的, p.Num是一个正数
		_, err := partner.UpdateCard(p.Num, b.Uid, false, o)
		if err != nil {
			o.Rollback()
			//把钻石还回去
			ok := client.ChangeAccountValueFromLobby(b.Uid, p.Num,
				0, 0, ACCTRAN_OPER_TYPE_TransferCard, 0)
			if !ok {
				eventLog := map[string]interface{}{
					"module":     ModuleSystem,
					"event_type": EventPlay,
					"user_type":  Agent,
					"uid":        b.Uid,
					"msg":        fmt.Sprintf("游戏服返回失败,把钻石还回去失败,请联系开发人员"),
				}
				go NewEventLog(eventLog)
				LogPF.Error(fmt.Sprintf("游戏服返回失败,合伙人代理(ID:%v)把钻石(%v)回充到游戏帐号失败", b.Uid, p.Num))
				LogPF.Error(b.DatabaseError(err.Error()))
				return
			}
		}
		o.Commit()
	}

	//代理帐号已有足够的钻石
	ok := client.ChangeAccountValueFromLobby(p.PlayerId, p.Num,
		0, 0, ACCTRAN_OPER_TYPE_BuyCard, 0)
	if !ok {
		eventLog := map[string]interface{}{
			"module":     ModuleSystem,
			"event_type": EventPlay,
			"user_type":  Player,
			"uid":        p.PlayerId,
			"msg":        fmt.Sprintf("游戏服返回失败,代充失败,请联系开发人员"),
		}
		go NewEventLog(eventLog)
		b.ResponseFail("代充失败,系统错误,请联系客户")
		LogPF.Error("游戏服返回失败,代充钻石失败")
		return
	}

	o := NewDBOrm(DBChessPartner)
	o.Begin()
	defer o.Rollback()

	//代充记录
	handleCR := map[string]interface{}{
		"agent_id":    b.Uid,
		"player_id":   p.PlayerId,
		"card_num":    -p.Num,
		"type":        HandleTopUp,
		"create_time": time.Now().Unix(),
	}

	_, err = partner.NewCardRecord(handleCR, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	//减去代理的钻石数量, p.Num是一个正数
	_, err = partner.UpdateCard(-p.Num, b.Uid, false, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	o.Commit()
	b.ResponseSuccess()
	//凡是在此代理充值过的玩家，不管是直充还是代充，都要记录到表里
	agentPlayer := map[string]interface{}{
		"create_time": time.Now().Unix(),
	}
	//不用管成功与否，不重要
	partner.UpdateOrInsertAgentPlayer(agentPlayer, p.PlayerId, b.Uid)
}

// @Title 代理进货时看到钻石列表
// @Description 代理进货时看到钻石列表
// @Success 0 {object} []common.Card
// @router /list-card [post]
func (b *CardController) ListCard() {
	card, err := partner.ListCard(RulePartnerCardPrice)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = card
	b.ResponseSuccess()
}

// @Title 代理赠送钻石时看到钻石列表
// @Description 代理赠送钻石时看到钻石列表
// @Success 0 {object} []common.Card
// @router /list-give-card [post]
func (b *CardController) ListGiveCard() {
	card, err := partner.ListCard(AgentGiveCard)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	restCard, err := partner.RestCard(b.Uid)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	data := map[string]interface{}{
		"rest_card": restCard,
		"list":      card,
	}
	b.Res.Data = data
	b.ResponseSuccess()
}
